package com.niiwoo.civet.mobile.controller.invest;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.rpc.RpcContext;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.niiwoo.civet.account.dto.request.InvestPayDubboRequestDTO;
import com.niiwoo.civet.account.dto.request.QueryMoneyTotalRequestDTO;
import com.niiwoo.civet.account.dto.response.AccountBaseResponse;
import com.niiwoo.civet.account.dto.response.QueryMoneyTotalResponseDTO;
import com.niiwoo.civet.account.service.AccountDubboService;
import com.niiwoo.civet.account.service.AccountInvestDubboService;
import com.niiwoo.civet.account.service.MoneyTotalDubboService;
import com.niiwoo.civet.base.constant.OrgConstant;
import com.niiwoo.civet.base.enums.ChannelCodeEnum;
import com.niiwoo.civet.mobile.util.MaskUtil;
import com.niiwoo.civet.mobile.util.MoneyUtil;
import com.niiwoo.civet.mobile.vo.common.*;
import com.niiwoo.civet.mobile.vo.request.invest.*;
import com.niiwoo.civet.mobile.vo.request.myloan.BackToArticleDayRequestVO;
import com.niiwoo.civet.mobile.vo.request.myloan.QueryBackToArticleByDayRequestVO;
import com.niiwoo.civet.mobile.vo.request.myloan.QueryProjectInfoRequestVO;
import com.niiwoo.civet.mobile.vo.response.creditor.FilterConfigResponseVO;
import com.niiwoo.civet.mobile.vo.response.invest.*;
import com.niiwoo.civet.mobile.vo.response.invest.UserAccountVO;
import com.niiwoo.civet.mobile.vo.response.myloan.BackToArticleByDayResponseVO;
import com.niiwoo.civet.mobile.vo.response.myloan.BackToArticleByMonResponseVO;
import com.niiwoo.civet.mobile.vo.response.myloan.InvestorPlanResponseVO;
import com.niiwoo.civet.mobile.vo.response.user.ProjectInvestorPlanResponseVO;
import com.niiwoo.civet.trade.dto.common.*;
import com.niiwoo.civet.trade.dto.request.*;
import com.niiwoo.civet.trade.dto.request.contract.CommissionAuthHistoryRequestDTO;
import com.niiwoo.civet.trade.dto.request.myloan.InvestingProjectPageRequestDTO;
import com.niiwoo.civet.trade.dto.request.myloan.MyloanRequestDTO;
import com.niiwoo.civet.trade.dto.response.*;
import com.niiwoo.civet.trade.dto.response.contract.CommissionAuthAgreementResponseDTO;
import com.niiwoo.civet.trade.dto.response.creditor.CreditorSaleDetailResponseDTO;
import com.niiwoo.civet.trade.dto.response.intelligenceInvest.ProjectPackageResponseDTO;
import com.niiwoo.civet.trade.dto.response.myloan.ProjectInvestorPlanResponseDTO;
import com.niiwoo.civet.trade.enums.*;
import com.niiwoo.civet.trade.service.creditor.CreditorRightsDubboService;
import com.niiwoo.civet.trade.service.intelligenceInvest.IntelligenceInvestDubboService;
import com.niiwoo.civet.trade.service.intelligenceInvest.IntelligenceOrderDubboService;
import com.niiwoo.civet.trade.service.invest.AutoInvestDubboService;
import com.niiwoo.civet.trade.service.invest.InvestDubboService;
import com.niiwoo.civet.trade.service.invest.InvestOrderDetailDubboService;
import com.niiwoo.civet.trade.service.myloan.MyLoanDubboService;
import com.niiwoo.civet.trade.service.project.ProjectDubboService;
import com.niiwoo.civet.user.dto.response.UserIdentityInfoResponseDTO;
import com.niiwoo.civet.user.dto.response.ValidUserForbidResponseDTO;
import com.niiwoo.civet.user.enums.UserEnum;
import com.niiwoo.civet.user.enums.UserForbidTypeEnum;
import com.niiwoo.civet.user.service.UserAuthorizationInfoDubboService;
import com.niiwoo.civet.user.service.UserForbidDubboService;
import com.niiwoo.civet.user.service.UserIdentityDubboService;
import com.niiwoo.civet.user.service.UserStatusDubboService;
import com.niiwoo.tripod.base.enums.UserTypeEnum;
import com.niiwoo.tripod.base.utils.BigDecimals;
import com.niiwoo.tripod.base.utils.IdCardUtils;
import com.niiwoo.tripod.lanmao.enums.UserRoleEnum;
import com.niiwoo.tripod.lanmao.response.LanMaoGatewayDTO;
import com.niiwoo.tripod.provider.dto.response.PageResponseDTO;
import com.niiwoo.tripod.provider.exception.BizException;
import com.niiwoo.tripod.web.annotation.AuthIgnore;
import com.niiwoo.tripod.web.component.AccessRateLimiter;
import com.niiwoo.tripod.web.shiro.UserAuthPrincipal;
import com.niiwoo.tripod.web.util.PrincipalContext;
import com.niiwoo.tripod.web.vo.PageRequestVO;
import com.niiwoo.tripod.web.vo.PageResponseVO;
import com.niiwoo.tripod.web.vo.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.math.BigDecimal;
import java.math.MathContext;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/userInvest")
@Api(tags = "投资(李想，张万里)", description = "/userInvest")
@Slf4j
public class UserInvestController {

    @Reference(version = "1.0.0")
    private InvestDubboService investDubboService;
    @Reference(version = "1.0.0")
    private InvestOrderDetailDubboService investOrderDetailDubboService;
    @Reference(version = "1.0.0")
    private AccountDubboService accountDubboService;
    @Reference(version = "1.0.0")
    private AccountInvestDubboService accountInvestDubboService;
    @Reference(version = "1.0.0")
    private AutoInvestDubboService autoInvestDubboService;
    @Reference(version = "1.0.0")
    private UserIdentityDubboService userIdentityDubboService;
    @Reference(version = "1.0.0")
    private MoneyTotalDubboService moneyTotalDubboService;
    @Reference(version = "1.0.0")
    private MyLoanDubboService myLoanDubboService;//回款计划
    @Reference(version = "1.0.0")
    private UserForbidDubboService userForbidDubboService;
    @Reference(version = "1.0.0")
    private UserStatusDubboService userStatusDubboService;
    @Reference(version = "1.0.0")
    private UserAuthorizationInfoDubboService userAuthorizationInfoDubboService;
    @Reference(version = "1.0.0")
    private ProjectDubboService projectDubboService;
    @Reference(version = "1.0.0")
    private CreditorRightsDubboService creditorRightsDubboService;
    @Reference(version = "1.0.0")
    private IntelligenceOrderDubboService intelligenceOrderDubboService;
    @Reference(version = "1.0.0")
    private IntelligenceInvestDubboService intelligenceInvestDubboService;
    @Value("${h5-invest-detail-url}")
    private String h5InvestDetailUrl;
    //极速借个人
    @Value("${h5-fastloan-contract-url}")
    private String h5FastloanContractUrl;
    //土巴兔
    @Value("${h5-orgloan-contract-url}")
    private String h5orgloanContractUrl;
    //鸿特个人
    @Value("${h5-OrgPersonalFastLoan-contract-url}")
    private String h5OrgPersonalFastLoanContract;
    //鸿特机构
    @Value("${h5-OrgCompanyFastLoan-contract-url}")
    private String h5OrgCompanyFastLoanContract;

    @Value("${h5-invest-detail-url-new}")
    private String h5InvestDetailUrlNew;

    //俊拓个人
    @Value("${h5-JunTuoPersonalFastLoan-contract-url}")
    private String h5JunTuoPersonalFastLoanContract;
    //俊拓机构
    @Value("${h5-JunTuoCompanyFastLoan-contract-url}")
    private String h5JunTuoCompanyFastLoanContract;
 
    @Value("${h5-invest-risk-tips-url}")
    private String h5InvestRiskTipsUrl;
    @Value("${h5-auto-invest-commission-auth-url}")
    private String h5AutoInvestCommissionAuthUrl;
    @Autowired
    private AccessRateLimiter accessRateLimiter;


    @PostMapping("/precondition")
    @ApiOperation("投资(设置)前置条件信息 (张万里)")
//    @AuthIgnore
    public Result<InvestSettingPreconditionResponseVO> queryInvestSettingPrecondition() throws Exception {
        InvestSettingPreconditionResponseVO responseVO = commPrecondition();
        responseVO.setContractUrl(this.h5FastloanContractUrl/* + "?borrowerUserId=%s&projectId=%s&addInvestor=1&addAmount=%s"*/);
        return Result.with(responseVO);
    }

    @PostMapping("/preconditionByType")
    @ApiOperation("投资前置条件信息 ,借款类型(刘春)")
    public Result<InvestSettingPreconditionResponseVO> queryInvestSettingPreconditionByType(@RequestBody InvestPreconditionRequestVO requestVO) throws Exception {
        InvestSettingPreconditionResponseVO responseVO = commPrecondition();
        ProjectDTO projectDTO = projectDubboService.selectProjectById(requestVO.getProjectId());
        String contractUrl = getContractUrl(projectDTO.getBorrowerType(), projectDTO.getType(),projectDTO.getOrgId(),projectDTO.getDeadlineUnit(), projectDTO.getLoanType());
        responseVO.setContractUrl(contractUrl/* + "&addAmount=%s&addInvestor=1"*/);
        return Result.with(responseVO);
    }

    @PostMapping("/creditPrecondition")
    @ApiOperation("债权投资前置条件信息 ,借款类型(刘春)")
    public Result<InvestSettingPreconditionResponseVO> queryCreditPrecondition(@RequestBody CreditPreconditionRequestVO creditPreconditionRequestVO) throws Exception {
        InvestSettingPreconditionResponseVO responseVO = commPrecondition();
        
        if (Byte.valueOf("2").equals(responseVO.getInvestorAccountStatus())) {
        	BigDecimal saleAmount = creditorRightsDubboService.getRealTimeCreditorSaleDetailSaleAmount(creditPreconditionRequestVO.getCreditorSaleDetailId(),
                    creditPreconditionRequestVO.getSaleUserId());
        	if (responseVO.getAmount().compareTo(saleAmount) < 0) {
                responseVO.setSufficient(Byte.valueOf("2"));
            }
        }
        return Result.with(responseVO);
    }

    /**
     * 投资(设置)前置条件信息
     *
     * @return
     * @throws Exception
     */
    private InvestSettingPreconditionResponseVO commPrecondition() throws Exception {
    	UserAuthPrincipal authPrincipal = PrincipalContext.getUserPrincipal();
        String userId = authPrincipal.getUserId();
        InvestSettingPreconditionResponseVO responseVO = new InvestSettingPreconditionResponseVO();
        //投资账户信息
        AccountBaseResponse accountInfo = null;
        if(UserTypeEnum.ORGANIZATION.equals(authPrincipal.getUserType())) {
        	//指定机构账户
        	accountInfo = accountDubboService.getOrgAccount(userId, userId);
        }else {
        	accountInfo = accountDubboService.getNiiwooAccount(userId, UserRoleEnum.INVESTOR);
        }
        if (accountInfo == null) {
            responseVO.setInvestorAccountStatus((byte) 0);
        } else {
            if (1 == accountInfo.getImportUserActiva()) {
                responseVO.setInvestorAccountStatus((byte) 2);
                responseVO.setAmount(accountInfo.getAvailableAmount());
            } else {
                responseVO.setInvestorAccountStatus((byte) 1);
            }
            responseVO.setNonePwdInvestStatus(accountInfo.getTender());
        }
        //风险测评信息
        Future<InvestEvaluationDTO> evaluationFuture = RpcContext.getContext().asyncCall(() -> investDubboService.getInvestEvaluationInfo(userId));
        Future<Integer> investingCountFuture = RpcContext.getContext().asyncCall(() -> investDubboService.getInvestingCount(userId));
        Future<ValidUserForbidResponseDTO> forbidFuture = RpcContext.getContext().asyncCall(() -> userForbidDubboService.queryValidUserForbidInfo(userId, UserForbidTypeEnum.INVESTOR));
        InvestEvaluationDTO evaluationDTO = evaluationFuture.get();
        responseVO.setHadEvaluate(evaluationDTO.getHadEvaluate());
        responseVO.setEvaluateLevel(evaluationDTO.getLevel());
        responseVO.setSurplusCanInvestAmount(evaluationDTO.getSurplusCanInvestAmount());
        ValidUserForbidResponseDTO forbidInfo = forbidFuture.get();
        Integer investingCount = investingCountFuture.get();
        if (investingCount >= 5) {
            responseVO.setIsPrompt(Byte.valueOf("1"));
        }
        //投资相关行为限制
        if (forbidInfo != null) {
            UserForbidVO forbidVO = new UserForbidVO(forbidInfo.getForbidType(), forbidInfo.getForbidTypeName(), forbidInfo.getForbidDesc());
            responseVO.setUserForbidList(Lists.newArrayList(forbidVO));
        }
        return responseVO;
    }



    @PostMapping("/addInvestEvaluation")
    @ApiOperation("投资风险类型测评")
    public Result<InvestEvaluationResponseVO> addInvestEvaluation(@RequestBody @Valid AddInvestEvaluationRequestVO request) {
        InvestEvaluationDTO investEvaluationDTO = investDubboService.addInvestEvaluation(PrincipalContext.getUserId(), request.getScore(), request.getIsDefOpeartion(), request.getIncomeSource());
        InvestEvaluationResponseVO result = new InvestEvaluationResponseVO();
        result.setHadEvaluate(investEvaluationDTO.getHadEvaluate());
        result.setCurrentYearTimes(investEvaluationDTO.getCurrentYearTimes());
        result.setIsDefOpeartion(investEvaluationDTO.getIsDefOpeartion());
        result.setScore(investEvaluationDTO.getScore());
        result.setLevel(investEvaluationDTO.getLevel());
        return Result.with(result);
    }

    @PostMapping("/getInvestEvaluationInfo")
    @ApiOperation("获取投资风险类型测评详情")
    public Result<InvestEvaluationResponseVO> getInvestEvaluationInfo() {
        String userId = String.valueOf(PrincipalContext.getUserId());
        InvestEvaluationDTO investEvaluationDTO = investDubboService.getInvestEvaluationInfo(userId);
        InvestEvaluationResponseVO result = new InvestEvaluationResponseVO();
        result.setHadEvaluate(investEvaluationDTO.getHadEvaluate());
        result.setCurrentYearTimes(investEvaluationDTO.getCurrentYearTimes());
        result.setIsDefOpeartion(investEvaluationDTO.getIsDefOpeartion());
        result.setScore(investEvaluationDTO.getScore());
        result.setLevel(investEvaluationDTO.getLevel());
        return Result.with(result);
    }

    @PostMapping("/investingSelector")
    @ApiOperation("可投资标的列表——筛选信息 (张万里)")
    @AuthIgnore
    public Result<List<SysInvestConfigOriginalVO>> queryInvestingSelector(@RequestBody @Valid InvestingSelectorRequestVO requestVO) {
        List<InvestingQueryCondtionConfigDTO> configDTOList = investDubboService.queryInvestingQueryCondtionConfig(BorrowerTypeEnum.typeOf(requestVO.getBorrowerType()));
        List<SysInvestConfigOriginalVO> sysConfigVOs = getSysInvestConfigOriginalVO(configDTOList);
        return Result.with(sysConfigVOs);
    }

    @PostMapping("/normalInvestingSelector")
    @ApiOperation("可投资散标的列表——筛选信息 (刘春)")
    @AuthIgnore
    public Result<FilterConfigResponseVO> queryNormalSelector(@RequestBody FilterTypeVo filterTypeVo) {
        FilterConfigResponseVO responseVO = new FilterConfigResponseVO();
        if (Byte.valueOf("1").equals(filterTypeVo.getFilterType()) ||
                /*Byte.valueOf("2").equals(filterTypeVo.getFilterType()) ||*/
                Byte.valueOf("3").equals(filterTypeVo.getFilterType())) {
            List<LinkAgeConfigVO> linkAgeConfigVO = new ArrayList<>();
            List<LinkAgeConfigDTO> queryResult = creditorRightsDubboService.queryCreditorSaleSelector(filterTypeVo.getFilterType());
            for(LinkAgeConfigDTO dto : queryResult){
                LinkAgeConfigVO vo = new LinkAgeConfigVO();
                vo.setInvestableType(dto.getInvestableType());
                vo.setPeriodType(dto.getPeriodType());
                vo.setProductType(dto.getProductType());
                vo.setRateType(dto.getRateType());
                vo.setRepaymentType(dto.getRepaymentType());
                linkAgeConfigVO.add(vo);
            }
            responseVO.setLinkageConfigs(linkAgeConfigVO);
        }
        return Result.with(responseVO);
    }

    @PostMapping("/normalInvestingSelectorH5")
    @ApiOperation("可投资的列表的筛选信息--H5 (谢稳)")
    @AuthIgnore
    public Result<List<FilterInvestConfigVO>> queryNormalSelector(){
        List<FilterInvestConfigVO> result = new ArrayList<>();

        FilterInvestConfigDTO queryResult = investDubboService.queryNormalInvestingSelector();
        FilterInvestConfigVO filterType = new FilterInvestConfigVO();
        filterType.setGroupName("1");
        filterType.setFilterType(queryResult.getFilterType());
        result.add(filterType);
        FilterInvestConfigVO periodType = new FilterInvestConfigVO();
        periodType.setGroupName("2");
        periodType.setFilterType(queryResult.getPeriodType());
        result.add(periodType);
        FilterInvestConfigVO rateType = new FilterInvestConfigVO();
        rateType.setGroupName("3");
        rateType.setFilterType(queryResult.getRateType());
        result.add(rateType);
        FilterInvestConfigVO repaymentType = new FilterInvestConfigVO();
        repaymentType.setGroupName("4");
        repaymentType.setFilterType(queryResult.getRepaymentType());
        result.add(repaymentType);
        return Result.with(result);
    }

    @PostMapping("/getMyInvestdetailH5")
    @ApiOperation("我的投资统计H5-谢稳")
    public Result<MyInvestdetailH5ResponseVO> getMyInvestdetailH5(){
        MyInvestdetailH5ResponseVO responseVO = new MyInvestdetailH5ResponseVO();

        UserAuthPrincipal principal = (UserAuthPrincipal) SecurityUtils.getSubject().getPrincipal();
        String userId = principal.getUserId();
        log.info("getMyInvestdetailH5用户userId:{}",userId);
        //String userId = "83010365-cc7a-4e3c-be53-1d9edfdad821";
        //大客户投资人 niiwoo机构
        AccountBaseResponse accountBase = accountDubboService.getOrgAccount(userId, userId);
        QueryMoneyTotalRequestDTO dto = new QueryMoneyTotalRequestDTO();
        dto.setUserId(userId);
        dto.setAccountId(accountBase == null ? null : accountBase.getAccountId());
        //momeyTotal汇总数据
        QueryMoneyTotalResponseDTO queryMoneyTotalResponseDTO = moneyTotalDubboService.queryMoneyTotal(dto);

        //回款中资金(待收本金)
        responseVO.setDueCapital(queryMoneyTotalResponseDTO.getDueInCorpus());
        //待收利息
        responseVO.setDueInterest(queryMoneyTotalResponseDTO.getDueInInterest());
        //待计息投资(投资冻结)
        responseVO.setFreezeCaptail(queryMoneyTotalResponseDTO.getInvestFreeze());
        //已赚利息
        responseVO.setRefundedInterest(queryMoneyTotalResponseDTO.getInvestIncome());
        //已完成投资(累计投资-待收本金)
        responseVO.setHadInvestCapital(queryMoneyTotalResponseDTO.getInvestTotal().subtract(queryMoneyTotalResponseDTO.getDueInCorpus()));
        responseVO.setTotalInterest(queryMoneyTotalResponseDTO.getInvestIncome().add(queryMoneyTotalResponseDTO.getDueInInterest()));
        responseVO.setTotalInvestCapital(queryMoneyTotalResponseDTO.getInvestTotal().add(queryMoneyTotalResponseDTO.getInvestFreeze()));
        return Result.with(responseVO);
    }

    private List<SysInvestConfigOriginalVO> getSysInvestConfigOriginalVO(List<InvestingQueryCondtionConfigDTO> sysConfigDTOs) {
        return sysConfigDTOs.stream().map(cfg -> {
            SysInvestConfigOriginalVO conf = new SysInvestConfigOriginalVO();
            BeanUtils.copyProperties(cfg, conf);
            return conf;
        }).collect(Collectors.toList());
    }

    @PostMapping("/investingPage")
    @ApiOperation("可投资标的列表——分页列表")
    @AuthIgnore
    public Result<InvestingProjectPageResponseVO> getInvestingProjectPage(@RequestBody @Valid InvestingProjectPageRequestVO request) {
        String userId = PrincipalContext.getUserId();
        if (userId != null) {
            boolean limit = accessRateLimiter.userLimit(userId, "investing-page", 1, AccessRateLimiter.Unit.SECOND, 10);
            if (limit) {
                throw new BizException("SYS1001");  //亲爱的用户，您操作频率过快，请稍后再试
            }
        }
        InvestingProjectPageResponseVO resultVO = new InvestingProjectPageResponseVO();
        if ("APP".equals(request.getChannelCode()) && request.getFilterType() != 1
                /*&& request.getFilterType() != 2*/ && request.getFilterType() != 0) {
            return Result.with(resultVO);
        }

        InvestingProjectPageRequestDTO investingProjectPageRequestDTO = new InvestingProjectPageRequestDTO();
        investingProjectPageRequestDTO.setChannelCode(StringUtils.isBlank(request.getChannelCode()) ? "APP" : request.getChannelCode());
        investingProjectPageRequestDTO.setIsSoldOut(request.getIsSoldOut());
        investingProjectPageRequestDTO.setOffset((request.getPageNumber() - 1) * request.getPageSize());
        investingProjectPageRequestDTO.setPageSize(request.getPageSize());
        InvestStdConfigVO periodConfig = request.getPeriodType();
        investingProjectPageRequestDTO.setProjectPeriod(validateNull(periodConfig) ? null :
                new ProjectPeriodDTO(Objects.isNull(periodConfig.getMinval()) ? null : periodConfig.getMinval().intValue(),
                        periodConfig.getMinvalCalSymbol(),
                        Objects.isNull(periodConfig.getMaxval()) ? null : periodConfig.getMaxval().intValue(),
                        periodConfig.getMaxvalCalSymbol(), periodConfig.getTermUnit().intValue()));
        InvestStdConfigVO rateConfig = request.getRateType();
        investingProjectPageRequestDTO.setProjectRatePeriod(validateNull(rateConfig) ? null :
                new ProjectRatePeriodDTO(Objects.isNull(rateConfig.getMinval()) ? null : rateConfig.getMinval().multiply(new BigDecimal(0.01).setScale(2,BigDecimal.ROUND_DOWN)),
                        rateConfig.getMinvalCalSymbol(),
                        Objects.isNull(rateConfig.getMaxval()) ? null : rateConfig.getMaxval().multiply(new BigDecimal(0.01).setScale(2,BigDecimal.ROUND_DOWN)),
                        rateConfig.getMaxvalCalSymbol()));
        InvestStdConfigVO investAmount = request.getInvestableType();

        investingProjectPageRequestDTO.setProjectInvestAmoun(validateNull(investAmount) ? null :
                new ProjectInvestAmountDTO(Objects.isNull(investAmount.getMinval()) ? null : investAmount.getMinval(),
                        investAmount.getMinvalCalSymbol(),
                        Objects.isNull(investAmount.getMaxval()) ? null : investAmount.getMaxval(),
                        investAmount.getMaxvalCalSymbol()));
        investingProjectPageRequestDTO.setProjectType(request.getProductType());
        investingProjectPageRequestDTO.setSort(request.getSort());
        investingProjectPageRequestDTO.setSortType(request.getSortType());
        investingProjectPageRequestDTO.setRepaymentType(request.getRepaymentType());
        investingProjectPageRequestDTO.setFiterType(request.getFilterType());
        PageResponseDTO<InvestingProjectDTO> investingProjectDTOS = investDubboService.getInvestingProjectPage(investingProjectPageRequestDTO,false);

        boolean isSoldOut = true;// 已售罄
        if(!CollectionUtils.isEmpty(investingProjectDTOS.getItems())){
            for (InvestingProjectDTO dto : investingProjectDTOS.getItems()) {
                InvestingProjectVO vo = this.convertToInvestingProjectVO(dto);
                resultVO.getItems().add(vo);
                if (request.getPageNumber() == 1) {// 第一页
                    if (vo.getProjectStatus() == 1) {
                        isSoldOut = false;
                    }
                }
            }
            resultVO.setTotalCount(investingProjectDTOS.getTotalCount());
            resultVO.setTotalPage(investingProjectDTOS.getTotalPage());
        }
        //5.4.0 配置联动后，由于配置期限过期后就找不到数据，  如果查询无数据，则在标的表查询对应三个月数据
        if(isSoldOut && CollectionUtils.isEmpty(investingProjectDTOS.getItems())){
            PageResponseDTO<InvestingProjectDTO> investingProjectPage = investDubboService.getInvestingProjectPage(investingProjectPageRequestDTO,true);
            for (InvestingProjectDTO dto : investingProjectPage.getItems()) {
                InvestingProjectVO vo = this.convertToInvestingProjectVO(dto);
                resultVO.getItems().add(vo);
            }
            resultVO.setTotalPage(investingProjectPage.getTotalPage());
            resultVO.setTotalCount(investingProjectPage.getTotalCount());
        }
        if (request.getPageNumber() == 1) {// 第一页
            resultVO.setIsSoldOut(isSoldOut ? Byte.valueOf("1") : Byte.valueOf("0"));
            if (isSoldOut) {// 已售罄
                resultVO.setSoldOutGuidanceResponseVO(this.getSoldOutGuidanceResponseVO(userId));
            }
        }
        return Result.with(resultVO);
    }

    private boolean validateNull(InvestStdConfigVO config) {
        if(Objects.isNull(config)){
            return true;
        }
        return Objects.isNull(config.getTermUnit()) && Objects.isNull(config.getTitle()) && Objects.isNull(config.getSeq());
    }

    @PostMapping("/investConfirm")
    @ApiOperation("投资确认")
    public Result<InvestConfirmResponseVO> investConfirm(@RequestBody @Valid InvestConfirmRequestVO request) {
    	request.setAmount(MoneyUtil.scale2HalfUp(request.getAmount()));//精度处理 
    	UserAuthPrincipal authPrincipal =  PrincipalContext.getUserPrincipal();
        // 判断行为禁止
        String userId = authPrincipal.getUserId();
        //频率验证
        timeLimit(userId);
        // 1生成投资订单
        InvestDubboRequest investDubboRequest = new InvestDubboRequest();
        investDubboRequest.setUserId(userId);
        investDubboRequest.setInvestAmount(request.getAmount());
        investDubboRequest.setProjectId(request.getProjectId());
        investDubboRequest.setPrizeId(request.getPrizeId());
        UserTypeEnum userType = authPrincipal.getUserType();
        investDubboRequest.setInvestUserType(Objects.isNull(userType)?UserTypeEnum.PERSONAL.getValue():userType.getValue());
        InvestOrderResponseDTO investOrderResponseDTO = investDubboService.invest(investDubboRequest);

        // 2投资订单支付
        InvestPayDubboRequestDTO investPayDubboRequestDTO = new InvestPayDubboRequestDTO();
        investPayDubboRequestDTO.setUserId(investDubboRequest.getUserId());
        investPayDubboRequestDTO.setProjectId(request.getProjectId());
        investPayDubboRequestDTO.setProjectType(investOrderResponseDTO.getProjectType());
        investPayDubboRequestDTO.setProjectTitle(investOrderResponseDTO.getProjectTitle());
        investPayDubboRequestDTO.setDeadline(investOrderResponseDTO.getDeadline());
        investPayDubboRequestDTO.setDeadlineUnit(investOrderResponseDTO.getDeadlineUnit());
        investPayDubboRequestDTO.setInvestAmount(investDubboRequest.getInvestAmount());
        investPayDubboRequestDTO.setInvestOrderId(investOrderResponseDTO.getInvestOrderId());
        investPayDubboRequestDTO.setExpired(investOrderResponseDTO.getExpired());
        investPayDubboRequestDTO.setNiiwooRedirectUrl(request.getNiiwooRedirectUrl());
        investPayDubboRequestDTO.setBorrowerUserId(investOrderResponseDTO.getBorrowUserId());
        if (Byte.valueOf("1").equals(investOrderResponseDTO.getTender())) {// 直连调用存管
            accountInvestDubboService.accountInvest(investPayDubboRequestDTO);
            return Result.with(new InvestConfirmResponseVO(Byte.valueOf("2"), null, null, investOrderResponseDTO.getInvestOrderId()));
        } else {// 网关调用存管
            LanMaoGatewayDTO lanMaoGatewayDTO = accountInvestDubboService.buildInvestPayGateWayParam(investPayDubboRequestDTO);
            return Result.with(new InvestConfirmResponseVO(Byte.valueOf("1"), lanMaoGatewayDTO.getAction(), lanMaoGatewayDTO.getParams(), null));
        }
    }

    @PostMapping("/crediteConfirm")
    @ApiOperation("债权投资确认")
    public Result<InvestConfirmResponseVO> crediteConfirm(@RequestBody @Valid CrediteConfirmRequestVO request) {
    	request.setAmount(MoneyUtil.scale2HalfUp(request.getAmount()));
    	
        // 判断行为禁止
        String userId = PrincipalContext.getUserId();
        //确认前置验证  用户行为限制，风险投资上限验证，访问时间间隔限制
        confirmPreCondition(userId, request.getAmount());
        if (userId.equals(request.getCreditorSaleDetailUserId())) {
            throw new BizException("TRD1000019");//债权认购人不能使债权出让人
        }

        // 1生成投资订单
        InvestCreditDubboRequest investDubboRequest = new InvestCreditDubboRequest();
        investDubboRequest.setUserId(userId);
        investDubboRequest.setCreditorSaleUserId(request.getCreditorSaleDetailUserId());//出让人ID
        investDubboRequest.setInvestAmount(request.getAmount());
        investDubboRequest.setCreditorSaleDetailId(request.getCreditorSaleDetailId());//债权出让DI
        InvestCreditResponseDTO investCreditResponseDTO = investDubboService.investCreditor(investDubboRequest);
        // 2投资订单支付
        InvestPayDubboRequestDTO investPayDubboRequestDTO = new InvestPayDubboRequestDTO();
        investPayDubboRequestDTO.setUserId(investDubboRequest.getUserId());
        investPayDubboRequestDTO.setProjectId(investCreditResponseDTO.getProjectId());
        investPayDubboRequestDTO.setProjectType(investCreditResponseDTO.getProjectType());//债权标类型
        investPayDubboRequestDTO.setProjectTitle(investCreditResponseDTO.getProjectTitle());
        investPayDubboRequestDTO.setDeadline(investCreditResponseDTO.getDeadline());
        investPayDubboRequestDTO.setDeadlineUnit(investCreditResponseDTO.getDeadlineUnit());
        investPayDubboRequestDTO.setInvestAmount(investDubboRequest.getInvestAmount());
        investPayDubboRequestDTO.setInvestOrderId(investCreditResponseDTO.getInvestOrderId());
        investPayDubboRequestDTO.setExpired(investCreditResponseDTO.getExpired());
        investPayDubboRequestDTO.setNiiwooRedirectUrl(request.getNiiwooRedirectUrl());
        investPayDubboRequestDTO.setBorrowerUserId(investCreditResponseDTO.getBorrowUserId());//出让人用户ID
        investPayDubboRequestDTO.setInvestType(Byte.valueOf("2"));//投资类型 债权
        investPayDubboRequestDTO.setShare(investCreditResponseDTO.getShare());
        investPayDubboRequestDTO.setCreditsaleRequestNo(investCreditResponseDTO.getCreditsaleRequestNo());//债权申请装让流水号
        investPayDubboRequestDTO.setCreditsaleId(investCreditResponseDTO.getCreditorSaleDetailId());//债权出售ID
        if (Byte.valueOf("1").equals(investCreditResponseDTO.getTender())) {// 直连调用存管
            log.info("债权投资执行直连预处理，投资人{},债权ID{}，债权出让人{}，投资金额{}", userId, investCreditResponseDTO.getCreditorSaleDetailId(),
                    investCreditResponseDTO.getBorrowUserId(), investDubboRequest.getInvestAmount());
            accountInvestDubboService.accountInvest(investPayDubboRequestDTO);
            return Result.with(new InvestConfirmResponseVO(Byte.valueOf("2"), null, null, investCreditResponseDTO.getInvestOrderId()));
        } else {// 网关调用存管
            log.info("债权投资执行网关预处理，投资人{},债权ID{}，债权出让人{}，投资金额{}", userId, investCreditResponseDTO.getCreditorSaleDetailId(),
                    investCreditResponseDTO.getBorrowUserId(), investDubboRequest.getInvestAmount());
            LanMaoGatewayDTO lanMaoGatewayDTO = accountInvestDubboService.buildInvestPayGateWayParam(investPayDubboRequestDTO);
            return Result.with(new InvestConfirmResponseVO(Byte.valueOf("1"), lanMaoGatewayDTO.getAction(), lanMaoGatewayDTO.getParams(), null));
        }
    }

    /**
     * 投资确认前置条件认证
     *
     * @param userId
     * @param amount
     */
    private void confirmPreCondition(String userId, BigDecimal amount) {
        userForbidDubboService.validUserForbidInfo(userId, UserForbidTypeEnum.INVESTOR);
        //验证用户的当前投资金额是否已达该风险类型投资上限
        investDubboService.vaildSurplusCanInvestAmount(userId, amount);
        timeLimit(userId);
    }
    
    private void timeLimit(String userId) {
    	boolean limit = accessRateLimiter.userLimit(userId, "manual-invest", 1, AccessRateLimiter.Unit.SECOND, 1);
        if (limit) {
            throw new BizException("SYS1001");  //亲爱的用户，您操作频率过快，请稍后再试
        }
    }

    @PostMapping("/getInvestorStatistics")
    @ApiOperation("获取投资人统计信息")
    public Result<InvestorStatisticsResponseVO> getInvestorStatistics() {
        QueryMoneyTotalRequestDTO requestDTO = new QueryMoneyTotalRequestDTO();
        requestDTO.setUserId(String.valueOf(PrincipalContext.getUserId()));
        QueryMoneyTotalResponseDTO dto = moneyTotalDubboService.queryMoneyTotal(requestDTO);
        InvestorStatisticsResponseVO responseVO = new InvestorStatisticsResponseVO();
        responseVO.setBackingAmount(dto.getDueInCorpusInterest());// 待收本息
        responseVO.setBackingCapital(dto.getDueInCorpus());// 待收本金
        responseVO.setBackingInterest(dto.getDueInInterest());// 待收利息
        responseVO.setInvestProfit(dto.getInvestIncome());// 投资收益
        responseVO.setInvestAward(dto.getInvestGiven());// 投资奖励
        responseVO.setIsExistCredit(dto.getIsExistCredit());//是否存在信用借
        responseVO.setIsOrgLoan(dto.getIsOrgLoan());//是否存在机构极速借
        return Result.with(responseVO);
    }

    @PostMapping("/getMyInvestOrderPage")
    @ApiOperation("分页获取我的投资订单列表")
    public Result<MyInvestOrderPageResponseVO> getMyInvestOrderPage(@RequestBody @Valid MyInvestOrderPageRequestVO request) throws Exception {
        String userId = PrincipalContext.getUserId();
        Future<UserIdentityInfoResponseDTO> identityFuture = RpcContext.getContext().asyncCall(() -> userIdentityDubboService.get(userId));
        List<InvestOrderDTO> investOrderDTOS = investDubboService.getMyInvestOrderPage(userId, request.getOrderStatus(), request.getPageNumber(), request.getPageSize());
        MyInvestOrderPageResponseVO myInvestOrderPageResponseVO = new MyInvestOrderPageResponseVO();
        for (InvestOrderDTO investOrderDTO : investOrderDTOS) {
            MyInvestOrderPageResponseVO.InvestOrderVO vo = new MyInvestOrderPageResponseVO.InvestOrderVO();
            vo.setBorrowerType(investOrderDTO.getBorrowerType());
            vo.setInvestOrderId(investOrderDTO.getInvestOrderId());
            vo.setProjectId(investOrderDTO.getProjectId());
            vo.setProjectType(investOrderDTO.getProjectType());
            vo.setBorrowerUserId(investOrderDTO.getBorrowerUserId());
            vo.setBorrowerGender(investOrderDTO.getBorrowerGender());
            vo.setBorrowerHeadImage(investOrderDTO.getBorrowerHeadImage());

            if (BorrowerTypeEnum.COMPANY.getType().equals(investOrderDTO.getBorrowerType())) {
                vo.setBorrowerNickName(MaskUtil.maskCompanyName(investOrderDTO.getBorrowerNickName()));
            } else {
                vo.setBorrowerNickName(investOrderDTO.getBorrowerNickName());
            }

            vo.setBorrowerNiiwooScore(investOrderDTO.getBorrowerNiiwooScore());
            vo.setBorrowerLoanTimes(investOrderDTO.getBorrowerLoanTimes());
            vo.setLoanCity(investOrderDTO.getLoanCity());
            vo.setLoanArea(investOrderDTO.getLoanArea());
            vo.setFullSuccessDate(investOrderDTO.getFullSuccessDate());
            vo.setTitle(investOrderDTO.getTitle());
            vo.setBorrowRate(investOrderDTO.getBorrowRate());
            vo.setBorrowRateDesc(BigDecimals.formatBorrowRate(investOrderDTO.getBorrowRate()));
            vo.setDeadLine(investOrderDTO.getDeadLine());
            vo.setDeadLineUnit(investOrderDTO.getDeadLineUtit());
            vo.setContractAmount(investOrderDTO.getContractAmount());
            vo.setOrderStatus(investOrderDTO.getOrderStatus());
            vo.setInvestedAmount(investOrderDTO.getInvestedAmount());
            vo.setInterest(investOrderDTO.getInterest().add(investOrderDTO.getAddInterest()));

            vo.setH5InvestDetailUrl(this.h5InvestDetailUrl + investOrderDTO.getInvestOrderId());
            vo.setCurrentPeriod(investOrderDTO.getCurrentPeriod());
            vo.setOverdueTip(investOrderDTO.getOverdueTip());
            if (null == investOrderDTO.getContractUrl()) {
                String contractUrl = getContractUrl(investOrderDTO.getBorrowerType(), investOrderDTO.getProjectType(), investOrderDTO.getOrgId(), investOrderDTO.getDeadLineUtit(), investOrderDTO.getLoanType());
                contractUrl = contractUrl + "&addInvestor=0";
                vo.setContractUrl(String.format(contractUrl, investOrderDTO.getBorrowerUserId(), investOrderDTO.getProjectId()));
            } else {
                vo.setContractUrl(investOrderDTO.getContractUrl());
            }
            if (investOrderDTO.getRiskTipsContractUrl() == null) {
                UserIdentityInfoResponseDTO identityDTO = identityFuture.get();
                vo.setRiskTipsContractUrl(identityDTO == null ? h5InvestRiskTipsUrl : h5InvestRiskTipsUrl + URLEncoder.encode(identityDTO.getName(), "utf-8"));
            } else {
                vo.setRiskTipsContractUrl(investOrderDTO.getRiskTipsContractUrl());
            }
            vo.setPublishTime(investOrderDTO.getPublishTime());
            myInvestOrderPageResponseVO.getItems().add(vo);
        }

        return Result.with(myInvestOrderPageResponseVO);
    }

    @PostMapping("/getFirstPagProjectList")
    @ApiOperation("获取首页投资理财标列表")
    @AuthIgnore
    public Result<InvestingProjectListResponseVO> getFirstPageProjectList(FirstPageProjectVO firstPageProjectVO) {

        String channelCode = firstPageProjectVO.getChannelCode();
        List<InvestingProjectDTO> dtos = investDubboService.getInvestingProjectListGroupByDeadLine(channelCode);
        InvestingProjectListResponseVO responseVO = new InvestingProjectListResponseVO();
        for (InvestingProjectDTO projectDTO : dtos) {
            InvestingProjectVO projectVO = this.convertToInvestingProjectVO(projectDTO);
            responseVO.getItems().add(projectVO);
        }
        return Result.with(responseVO);
    }

    /**
     * 可投标的列表DTO转VO
     *
     * @param dto
     * @return
     */
    private InvestingProjectVO convertToInvestingProjectVO(InvestingProjectDTO dto) {
        InvestingProjectVO vo = new InvestingProjectVO();
        vo.setProjectId(dto.getProjectId());
        vo.setProjectType(dto.getProjectType());
        vo.setUserPrizeSuitProjectType(ProjectTypeEnum.getEnum(dto.getProjectType()).getUserPrizeSuitProjectType());
        vo.setBorrowerUserId(dto.getBorrowerUserId());
        vo.setBorrowerHeadImage(dto.getBorrowerHeadImage());

        if (BorrowerTypeEnum.COMPANY.getType().equals(dto.getBorrowerType())) {
            vo.setBorrowerNickName(MaskUtil.maskCompanyName(dto.getBorrowerNickName()));
        } else {
            vo.setBorrowerNickName(dto.getBorrowerNickName());
        }
        vo.setLoanType(dto.getLoanType());
        vo.setLoanTypeDesc(dto.getLoanTypeDesc());
        vo.setIsMasterBorrower(dto.getIsMasterBorrower());
        vo.setBorrowerGender(dto.getBorrowerGender());
        vo.setBorrowerNiiwooScore(dto.getBorrowerNiiwooScore());
        vo.setLoanTimes(dto.getLoanTimes());
        vo.setCity(dto.getCity());
        vo.setArea(dto.getArea());
        vo.setPublishTime(dto.getPublishTime());
        vo.setTitle(dto.getTitle());
        vo.setBorrowRate(dto.getBorrowRate());
        vo.setBorrowRateDesc(BigDecimals.formatBorrowRate(dto.getBorrowRate()));
        vo.setDeadline(dto.getDeadline());
        vo.setDeadlineUnit(dto.getDeadlineUnit());
        vo.setContractAmount(dto.getContractAmount());
        vo.setInvestingAmount(dto.getInvestingAmount());
        vo.setProjectStatus(dto.getProjectStatus());
        vo.setCreditType(dto.getCreditType());
        vo.setBorrowerType(dto.getBorrowerType());
        vo.setRepaymentType(dto.getRepaymentType());
        vo.setBaseInvestMoney(dto.getBaseInvestMoney());
        if (Objects.nonNull(dto.getInterestAddRate())) {
            InvestingProjectVO.ActivityInfo activityInfo = new InvestingProjectVO.ActivityInfo();
            activityInfo.setActivityTitle(dto.getInterestAddTitle());
            activityInfo.setIncreaseInterest(dto.getInterestAddRate());
            vo.setActivityInfo(activityInfo);
        }
        return vo;
    }


    @PostMapping("/getRecomendProjectList")
    @ApiOperation("猜你想投标的列表")
    @AuthIgnore
    public Result<InvestingProjectListResponseVO> getRecomendProjectList(@RequestBody @Valid RecommendProjectListRequestVO request) {
        List<InvestingProjectDTO> list = investDubboService.getRecomendProjectList(request.getProjectId(),
                request.getBorrowUserId(), request.getChannelCode());
        InvestingProjectListResponseVO resultVO = new InvestingProjectListResponseVO();
        for (InvestingProjectDTO investingProjectDTO : list) {
            resultVO.getItems().add(this.convertToInvestingProjectVO(investingProjectDTO));
        }
        return Result.with(resultVO);
    }

    @PostMapping("/getInvestingProjectByProjectId")
    @ApiOperation("通过标的id获取标的信息（用于刷新可投资标的列表的指定标的信息）")
    @AuthIgnore
    public Result<List<FreshInvestingProjectVO>> getInvestingProjectByProjectIdArray(@RequestBody @Valid ProjectIdArrayRequestVO projectIdArrayRequestVO) {
        List<Long> projectIdList = projectIdArrayRequestVO.getProjectIdList();
        if (null == projectIdList || projectIdList.size() == 0) {
            throw new BizException("TRD10004");// 参数不合法
        }

        List<FreshInvestingProjectDTO> investingProjectDTOS = investDubboService.getInvestingProjectInfo(projectIdList);
        List<FreshInvestingProjectVO> resultList = new ArrayList<>();
        if (investingProjectDTOS != null && investingProjectDTOS.size() != 0) {
            for (FreshInvestingProjectDTO investingProjectDTO : investingProjectDTOS) {
                FreshInvestingProjectVO vo = new FreshInvestingProjectVO(investingProjectDTO.getProjectId(),
                        investingProjectDTO.getRemainAmount(), investingProjectDTO.getStatus());
                resultList.add(vo);
            }
        }
        return Result.with(resultList);
    }

    @PostMapping("/getProjectInvestOrderList")
    @ApiOperation("获取标的投资订单(人)列表")
    @AuthIgnore
    public Result<ProjectInvestOrderListResponseVO> getProjectInvestOrderList(@RequestBody @Valid ProjectIdRequestVO projectIdRequestVO) {
        ProjectInvestOrderPageRequest request = new ProjectInvestOrderPageRequest();
        request.setProjectId(projectIdRequestVO.getProjectId());
        request.setOffset((projectIdRequestVO.getPageNumber() - 1) * projectIdRequestVO.getPageSize());
        request.setPageSize(projectIdRequestVO.getPageSize());

        ProjectInvestOrderListResponseVO result = new ProjectInvestOrderListResponseVO();
        ProjectInvestOrderPageResponse response;
        if (projectIdRequestVO.getRequestType() == 2) {
            response = intelligenceOrderDubboService.getPageIntelligenceInvestOrderList(request);
        } else {
            response = investDubboService.getPageProjectInvestOrderList(request);
        }
        result.setTotalRecord(response.getTotalRecord());

        for (InvestedOrderDTO investedOrderDTO : response.getDataList()) {
            ProjectInvestOrderListResponseVO.ProjectInvestOrderVO vo = new ProjectInvestOrderListResponseVO.ProjectInvestOrderVO();
            vo.setInvestUserId(investedOrderDTO.getInvestUserId());
            vo.setAmount(investedOrderDTO.getAmount());
            vo.setInvestorHeadImage(investedOrderDTO.getInvestorHeadImage());

            if (ChannelCodeEnum.KAOLA.getFinanceFlag().equals(investedOrderDTO.getChannelCode())) {
                if (StringUtils.isNoneEmpty(investedOrderDTO.getIdCard(), investedOrderDTO.getRealName())) {
                    if ("M".equals(IdCardUtils.getGenderByIdCard(investedOrderDTO.getIdCard()))) {
                        vo.setInvestorGender((byte) UserEnum.Gender.MALE.getValue());
                        vo.setInvestorNickName(investedOrderDTO.getRealName().charAt(0) + "先生");
                    } else {
                        vo.setInvestorGender((byte) UserEnum.Gender.FEMALE.getValue());
                        vo.setInvestorNickName(investedOrderDTO.getRealName().charAt(0) + "女士");
                    }
                }
            } else {
                vo.setInvestorNickName(investedOrderDTO.getInvestorNickName());
                vo.setInvestorGender(investedOrderDTO.getInvestorGender());
            }

            vo.setInvestorNiiwooScore(investedOrderDTO.getInvestorNiiwooScore());
            vo.setInvestTime(investedOrderDTO.getInvestTime());
            vo.setChannelCode(investedOrderDTO.getChannelCode());

            result.getItems().add(vo);
        }
        return Result.with(result);
    }

    @PostMapping("/getInvestAvailableAmount")
    @ApiOperation("获取投资账户可用余额")
    public Result<UserAccountVO> getInvestAvailableAmount(@RequestBody @Valid ProjectIdRequestVO request) {
        UserAuthPrincipal userAuthPrincipal = PrincipalContext.getUserPrincipal();
        log.info("getInvestAvailableAmount userAuthPrincipal:{}", JSON.toJSON(userAuthPrincipal));
        String userId = String.valueOf(userAuthPrincipal.getUserId());
        AccountBaseResponse accountBase;
        if(userAuthPrincipal.getUserType() != null && UserTypeEnum.ORGANIZATION.getValue().equals(userAuthPrincipal.getUserType().getValue())) {
            accountBase = accountDubboService.getOrgAccount(userId, userId);
        }else {
            accountBase = accountDubboService.loadNiiwooAccount(userId, UserRoleEnum.INVESTOR);
        }
        if(Objects.nonNull(accountBase)) {
        	accountBase =accountDubboService.loadAccountByIdFromMaster(accountBase.getAccountId());
        }
        BigDecimal avilibleAmount = BigDecimal.ZERO;
        if(Byte.valueOf("1").equals(request.getRequestType())) {
        	List<FreshInvestingProjectDTO> investingProjectDTOS = investDubboService.getInvestingProjectInfo(Arrays.asList(request.getProjectId()));
        	avilibleAmount = investingProjectDTOS.get(0).getRemainAmount();
        }else if(Byte.valueOf("2").equals(request.getRequestType())) {
        	ProjectPackageResponseDTO packageInfo = intelligenceInvestDubboService.getIntelligenceInvestInfo(request.getProjectId());
        	avilibleAmount  = packageInfo.getAmount().subtract(packageInfo.getInvestedAmount());
        }
        return Result.with(new UserAccountVO(accountBase == null ? BigDecimal.ZERO : accountBase.getAvailableAmount(),avilibleAmount ));
    }

    @PostMapping("/backToArticleDay")
    @ApiOperation("回款计划-查询回款日期与当日回款总本金总利息(廖君君)")
    public Result<PageResponseVO<BackToArticleByDayResponseVO>> backToArticleDay(@RequestBody BackToArticleDayRequestVO requestVO) {
        String userId = String.valueOf(PrincipalContext.getUserId());
        MyloanRequestDTO dto = new MyloanRequestDTO();
        dto.setUserId(userId);
        dto.setPageSize(requestVO.getPageSize());
        dto.setPageNumber(requestVO.getPageNumber());
        if(Objects.nonNull(requestVO.getStartTime()) && requestVO.getStartTime().getTime() != 0L){
            dto.setStartTime(requestVO.getStartTime());
        }
        if(Objects.nonNull(requestVO.getEndTime()) && requestVO.getEndTime().getTime() != 0L){
            dto.setEndTime(requestVO.getEndTime());
        }

        if(Objects.nonNull(requestVO.getQueryWay()) && requestVO.getQueryWay() != 0){
            //1.查询未来一月 2.查询未来三月 3.查询未来半年 4.查询未来全部
            DateTime toDay = new DateTime();
            dto.setStartTime(toDay.toDate());
            if(requestVO.getQueryWay() == 1){
                dto.setEndTime(toDay.plusMonths(1).toDate());
            }else if(requestVO.getQueryWay() == 2){
                dto.setEndTime(toDay.plusMonths(3).toDate());
            }else if(requestVO.getQueryWay() == 3){
                dto.setEndTime(toDay.plusMonths(6).toDate());
            }else if(requestVO.getQueryWay() == 4){
                dto.setEndTime(null);
            }
        }
        return Result.with(JSON.parseObject(JSON.toJSONString(myLoanDubboService.backToArticleDay(dto)),
                PageResponseVO.class));
    }

    @PostMapping("/backToArticleByDay")
    @ApiOperation("回款计划-按日查看回款计划明细(廖君君)")
    public Result<PageResponseVO<InvestorPlanResponseVO>> backToArticleByDay(@RequestBody QueryBackToArticleByDayRequestVO vo) {
        String userId = String.valueOf(PrincipalContext.getUserId());
        MyloanRequestDTO dto = new MyloanRequestDTO();
        dto.setUserId(userId);
        dto.setH5InvestDetailUrl(this.h5InvestDetailUrlNew);
        dto.setPageNumber(vo.getPageNumber());
        dto.setPageSize(vo.getPageSize());
        return Result.with(JSON.parseObject(JSON.toJSONString(myLoanDubboService.backToArticleDayByDay(dto, vo.getReceivedDate())),
                PageResponseVO.class));
    }

    @PostMapping("/backToArticleByMon")
    @ApiOperation("回款计划-按月查看(宾村)")
    public Result<PageResponseVO<BackToArticleByMonResponseVO>> backToArticleByMon(@RequestBody PageRequestVO vo) {
        String userId = String.valueOf(PrincipalContext.getUserId());
        MyloanRequestDTO dto = new MyloanRequestDTO();
        dto.setUserId(userId);
        dto.setPageNumber(vo.getPageNumber());
        dto.setPageSize(vo.getPageSize());
        return Result.with(JSON.parseObject(JSON.toJSONString(myLoanDubboService.listBackToArticleByMonth(dto)),
                PageResponseVO.class));

    }

    @AuthIgnore
    @PostMapping("/listProjectInvestorPlan")
    @ApiOperation("标的详情还款方式-投资人")
    public Result<ProjectInvestorPlanResponseVO> listProjectInvestorPlan(@RequestBody @Valid QueryProjectInfoRequestVO requestVO) {
        String userId = String.valueOf(PrincipalContext.getUserId());

        ProjectInvestorPlanResponseVO responseVO = new ProjectInvestorPlanResponseVO();
        ProjectInvestorPlanResponseDTO responseDTO = myLoanDubboService.queryProjectInvestorPlan(userId, requestVO.getProjectId());
        responseVO.setInterestTotal(responseDTO.getInterestTotal());
        responseVO.setReceivableTotalAmount(responseDTO.getReceivableTotalAmount());
        responseVO.setInvestAmount(responseDTO.getInvestAmount());
        responseVO.setIsInvest(responseDTO.getIsInvest());
        responseVO.setProjectState(responseDTO.getProjectState());
        responseVO.setFullSuccessTime(responseDTO.getFullSuccessTime());
        for (ProjectInvestorPlanResponseDTO.ReceivableRecords records : responseDTO.getReceivableRecords()) {
            ProjectInvestorPlanResponseVO.ReceivableRecords receivableRecords = new ProjectInvestorPlanResponseVO.ReceivableRecords();
            receivableRecords.setReceivableAmount(records.getReceivableAmount());
            receivableRecords.setReceivableRate(records.getReceivableRate());
            receivableRecords.setReceiveDate(records.getReceiveDate());
            receivableRecords.setTotalAmount(records.getTotalAmount());
            responseVO.getReceivableRecords().add(receivableRecords);
        }
        return Result.with(responseVO);
    }

    @PostMapping("/getInvestOrderDetail")
    @ApiOperation("获取投资订单详情")
    public Result<InvestOrderDetailResponseVO> getInvestOrderDetail(@RequestBody @Valid InvestOrderIdRequestVO request) {
        InvestOrderDetailDubboDTO orderDetailDTO = investOrderDetailDubboService.getInvestOrderDetail(request.getInvestOrderId());
        Byte evolutionStatus = orderDetailDTO.getEvolutionStatus();
        Byte deadlineUnit = orderDetailDTO.getDeadlineUnit();
        InvestOrderDetailResponseVO result = new InvestOrderDetailResponseVO();
        result.setEvolutionStatus(evolutionStatus);
        result.setDeadlineUnit(deadlineUnit);
        if (ProjectInvestOrderEvolutionStatusEnum.INVESTING.getValue().equals(evolutionStatus)) {// 投资中
            InvestOrderDetailResponseVO.InvestingOrderDetailVO vo = new InvestOrderDetailResponseVO.InvestingOrderDetailVO();
            InvestOrderDetailDubboDTO.InvestingOrderDetailDTO dto = orderDetailDTO.getInvestingOrderDetailDTO();
            vo.setAmount(dto.getAmount());
            vo.setInterest(dto.getInterest());
            vo.setInvestedAmount(dto.getInvestedAmount());
            vo.setContractAmount(dto.getContractAmount());
            vo.setInvestEndTime(dto.getInvestEndTime());
            vo.setIsFull(dto.getIsFull());
            vo.setDesc(dto.getDesc());
            result.setInvestingOrderDetailVO(vo);
        } else if (ProjectInvestOrderEvolutionStatusEnum.BACKING.getValue().equals(evolutionStatus)
                || ProjectInvestOrderEvolutionStatusEnum.BACKING_OVERDUE.getValue().equals(evolutionStatus)) {// 投资订单详情（回款中||回款逾期）
            if (Byte.valueOf("1").equals(deadlineUnit)) {// 月标
                InvestOrderDetailResponseVO.MonthProjectBackingOrderDetailVO vo = new InvestOrderDetailResponseVO.MonthProjectBackingOrderDetailVO();
                InvestOrderDetailDubboDTO.MonthProjectBackingOrderDetailDTO dto = orderDetailDTO.getMonthProjectBackingOrderDetailDTO();
                vo.setBackingAmount(dto.getBackingAmount());
                vo.setBackedAmount(dto.getBackedAmount());
                vo.setBackedPeriod(dto.getBackedPeriod());
                vo.setAmount(dto.getAmount());
                vo.setInterest(dto.getInterest());
                vo.setTotalPeriods(dto.getTotalPeriods());
                vo.setRepaymentType(dto.getRepaymentType());

                vo.setHaveAddInterest(dto.getHaveAddInterest());
                vo.setBackPlanVOList(this.formatToBackPlanVOList(dto.getBackPlanDTOList()));
                result.setMonthProjectBackingOrderDetailVO(vo);
            } else {// 天标
                InvestOrderDetailResponseVO.DayProjectBackingOrderDetailVO vo = new InvestOrderDetailResponseVO.DayProjectBackingOrderDetailVO();
                InvestOrderDetailDubboDTO.DayProjectBackingOrderDetailDTO dto = orderDetailDTO.getDayProjectBackingOrderDetailDTO();
                vo.setBackingAmount(dto.getBackingAmount());
                vo.setBackedAmount(dto.getBackedAmount());
                vo.setDeadline(dto.getDeadline());
                vo.setAmount(dto.getAmount());
                vo.setInterest(dto.getInterest());
                vo.setAddInterest(dto.getAddInterest());
                vo.setRepaymentType(dto.getRepaymentType());
                vo.setBackDate(dto.getBackDate());
                vo.setAddInterest(dto.getAddInterest());
                vo.setStatus(dto.getStatus());
                result.setDayProjectBackingOrderDetailVO(vo);
            }
        } else if (ProjectInvestOrderEvolutionStatusEnum.ALL_BACKED.getValue().equals(evolutionStatus)) {
            if (Byte.valueOf("1").equals(deadlineUnit)) {// 月标
                InvestOrderDetailResponseVO.MonthProjectBackedOrderDetailVO vo = new InvestOrderDetailResponseVO.MonthProjectBackedOrderDetailVO();
                InvestOrderDetailDubboDTO.MonthProjectBackedOrderDetailDTO dto = orderDetailDTO.getMonthProjectBackedOrderDetailDTO();
                vo.setAmount(dto.getAmount());
                vo.setInterest(dto.getInterest());
                vo.setTotalPeriods(dto.getTotalPeriods());
                vo.setRepaymentType(dto.getRepaymentType());
                vo.setHaveAddInterest(dto.getHaveAddInterest());
                vo.setBackPlanVOList(this.formatToBackPlanVOList(dto.getBackPlanDTOList()));
                result.setMonthProjectBackedOrderDetailVO(vo);
            } else {// 天标
                InvestOrderDetailResponseVO.DayProjectBackedOrderDetailVO vo = new InvestOrderDetailResponseVO.DayProjectBackedOrderDetailVO();
                InvestOrderDetailDubboDTO.DayProjectBackedOrderDetailDTO dto = orderDetailDTO.getDayProjectBackedOrderDetailDTO();
                vo.setAmount(dto.getAmount());
                vo.setInterestTotal(dto.getInterestTotal());
                vo.setRepaymentType(dto.getRepaymentType());
                vo.setBackDate(dto.getBackDate());
                vo.setInterest(dto.getInterest());
                vo.setAddInterest(dto.getAddInterest());
                vo.setStatus(dto.getStatus());
                result.setDayProjectBackedOrderDetailVO(vo);
            }
        } else {
            // do nothing
        }
        return Result.with(result);
    }

    /**
     * 回款计划DTO转VO
     *
     * @param backPlanDTOList
     * @return
     */
    private List<InvestOrderDetailResponseVO.BackPlanVO> formatToBackPlanVOList(List<InvestOrderDetailDubboDTO.BackPlanDTO> backPlanDTOList) {
        List<InvestOrderDetailResponseVO.BackPlanVO> backPlanVOList = new ArrayList<InvestOrderDetailResponseVO.BackPlanVO>();
        if (null != backPlanDTOList) {
            for (InvestOrderDetailDubboDTO.BackPlanDTO backPlanDTO : backPlanDTOList) {
                InvestOrderDetailResponseVO.BackPlanVO backPlanVO = new InvestOrderDetailResponseVO.BackPlanVO();
                backPlanVO.setAddInterest(backPlanDTO.getAddInterest());
                backPlanVO.setAmount(backPlanDTO.getAmount());
                backPlanVO.setBackDate(backPlanDTO.getBackDate());
                backPlanVO.setPeriod(backPlanDTO.getPeriod());
                backPlanVO.setStatus(backPlanDTO.getStatus());
                backPlanVO.setInterest(backPlanDTO.getInterest());
                backPlanVO.setAddInterest(backPlanDTO.getAddInterest());
                backPlanVOList.add(backPlanVO);
            }
        }
        return backPlanVOList;
    }

    @PostMapping("/getInvestSuccessInfo")
    @ApiOperation("获取投资成功信息")
    public Result<InvestSuccessInfoResponseVO> getInvestSuccessInfo(@RequestBody @Valid InvestOrderIdRequestVO request) {
        InvestSuccessInfoDTO investSuccessInfoDTO = investDubboService.getInvestSuccessInfo(request.getInvestOrderId());
        InvestSuccessInfoResponseVO resultVO = new InvestSuccessInfoResponseVO();
        resultVO.setStatus(investSuccessInfoDTO.getStatus());
        resultVO.setInvestAmount(investSuccessInfoDTO.getInvestAmount());
        resultVO.setInterest(investSuccessInfoDTO.getInterest());
        resultVO.setRemainingAmount(investSuccessInfoDTO.getRemainingAmount());
        resultVO.setTender(investSuccessInfoDTO.getTender());
        resultVO.setIsPrizeUsed(investSuccessInfoDTO.getIsPrizeUsed());
        resultVO.setPrizeName(investSuccessInfoDTO.getPrizeName());
        resultVO.setIsShowPrompt(investSuccessInfoDTO.getIsShowPrompt());
        String userId = investSuccessInfoDTO.getUserId();
        FastloanInvestSuccessDTO fastloanInvestSuccessDTO = investDubboService.getFastloanInvestSuccessDTO(userId);
        if (null != fastloanInvestSuccessDTO) {
            FastloanInvestSuccessResponseVO vo = new FastloanInvestSuccessResponseVO();
            vo.setButtonText(fastloanInvestSuccessDTO.getButtonText());
            vo.setContent(fastloanInvestSuccessDTO.getContent());
            vo.setIsShow(fastloanInvestSuccessDTO.getIsShow());
            vo.setLink(fastloanInvestSuccessDTO.getLink());
            vo.setPageType(fastloanInvestSuccessDTO.getPageType());
            vo.setTitle(fastloanInvestSuccessDTO.getTitle());
            resultVO.setFastloanInvestSuccessResponseVO(vo);
        }
        return Result.with(resultVO);
    }

    @PostMapping("/getCreditSuccessInfo")
    @ApiOperation("获取债权投资成功信息")
    public Result<CreditSuccessInfoResponseVO> getCreditSuccessInfo(@RequestBody @Valid InvestOrderIdRequestVO request) {

        CreditSuccessInfoDTO creditSuccessInfoDTO = investDubboService.getCreditSuccessInfo(request.getInvestOrderId());
        CreditSuccessInfoResponseVO creditSuccessInfoResponseVO = new CreditSuccessInfoResponseVO();
        if (Objects.nonNull(creditSuccessInfoDTO) && PrincipalContext.getUserId().equals(creditSuccessInfoDTO.getUserId())) {
            BeanUtils.copyProperties(creditSuccessInfoDTO, creditSuccessInfoResponseVO);
        }
        BigDecimal assigneeInterest = creditSuccessInfoResponseVO.getInvestAmount().add(creditSuccessInfoResponseVO.getOffAmount()).subtract(creditSuccessInfoResponseVO.getAmount());
        creditSuccessInfoResponseVO.setAssigneeInterest(assigneeInterest);
        return Result.with(creditSuccessInfoResponseVO);
    }

    private SoldOutGuidanceResponseVO getSoldOutGuidanceResponseVO(String userId) {
        InvestFlowConfigResponseDTO responseDTO = investDubboService.getSoldOutGuidance(userId);
        if (responseDTO != null) {
            SoldOutGuidanceResponseVO soldOutGuidanceResponseVO = new SoldOutGuidanceResponseVO();
            soldOutGuidanceResponseVO.setType(responseDTO.getType().getValue());
            soldOutGuidanceResponseVO.setContent(responseDTO.getContent());
            soldOutGuidanceResponseVO.setButtonText(responseDTO.getButtonText());
            soldOutGuidanceResponseVO.setLink(responseDTO.getLink());
            soldOutGuidanceResponseVO.setTitle(responseDTO.getTitle());
            soldOutGuidanceResponseVO.setIsShow(responseDTO.getIsShow());
            return soldOutGuidanceResponseVO;
        }
        return null;
    }

    @PostMapping("/getInvestOrderSimpleInfo")
    @ApiOperation("获取投资订单信息信息（投资订单详情页头）")
    public Result<InvestOrderSimpleInfoResponseVO> getInvestOrderSimpleInfo(@RequestBody @Valid InvestOrderIdRequestVO request) {
        InvestOrderSimpleInfoResponseDTO dto = investDubboService.getInvestOrderSimpleInfo(request.getInvestOrderId());
        InvestOrderSimpleInfoResponseVO vo = new InvestOrderSimpleInfoResponseVO();
        vo.setBorrowerHeadImage(dto.getBorrowerHeadImage());
        vo.setBorrowerUserId(dto.getBorrowerUserId());
        vo.setOrderStatus(dto.getOrderStatus());
        vo.setProjectId(dto.getProjectId());
        vo.setProjectTitle(dto.getProjectTitle());
        vo.setPublishTime(dto.getPublishTime());
        vo.setFullSuccessDate(dto.getFullSuccessDate());
        vo.setBorrowerType(dto.getBorrowerType());
        return Result.with(vo);
    }


    @PostMapping("/getFastLoanContractInfo")
    @ApiOperation("获取极速借居间借款合同信息")
    public Result<FastLoanContractResponseVO> getFastLoanContractInfo(@RequestBody @Valid ContractRequestVO request) {
        ContractRequestDTO contractRequestDTO = new ContractRequestDTO();
        contractRequestDTO.setBorrowerUserId(request.getBorrowerUserId());
        contractRequestDTO.setProjectId(request.getProjectId());
        contractRequestDTO.setAddInvestor(request.getAddInvestor());
        contractRequestDTO.setAddAmount(request.getAddAmount());
        FastLoanContractResponseDTO dto = investDubboService.getFastLoanContractInfo(contractRequestDTO, String.valueOf(PrincipalContext.getUserId()));
        FastLoanContractResponseVO vo = new FastLoanContractResponseVO();
        vo.setContractNo(dto.getContractNo());
        for (FastLoanContractResponseDTO.APart aPart : dto.getAPartList()) {
            FastLoanContractResponseVO.APart aPartVO = new FastLoanContractResponseVO.APart();
            aPartVO.setMoney(aPart.getAmount());
            aPartVO.setName(aPart.getName());
            aPartVO.setIdCard(aPart.getIdCard());
            vo.getAPartList().add(aPartVO);
        }
        vo.getBPart().setAddress(dto.getBPart().getAddress());
        vo.getBPart().setEmail("");
        vo.getBPart().setName(dto.getBPart().getName());
        vo.getBPart().setIdCard(dto.getBPart().getIdCard());
        vo.getCPart().setEmail("");
        vo.getCPart().setName(dto.getCPart().getName());
        vo.getCPart().setInstitutionalReditCode(dto.getCPart().getInstitutionalReditCode());
        vo.getDPart().setAddress(dto.getDPart().getAddress());
        vo.getDPart().setName(dto.getDPart().getName());
        vo.setAmount(dto.getAmount());
        vo.setDeadline(dto.getDeadline());
        vo.setBorrowRate(dto.getBorrowRate());
        vo.setLoanInterest(dto.getLoanInterest());
        vo.setRepaymentType(dto.getRepaymentType());
        vo.setProjectTitle(dto.getProjectTitle());
        vo.setRefundDate(dto.getRefundDate());
        vo.setPenaltyRate(dto.getPenaltyRate());
        vo.setPlatformManagementFee(dto.getPlatformManagementFee());
        vo.setPlatformManageFeeRate(dto.getPlatformManagementFee()
                .multiply(new BigDecimal(12))
                .divide(dto.getAmount(), MathContext.DECIMAL128)
                .divide(new BigDecimal(dto.getDeadline()), 4, BigDecimal.ROUND_HALF_EVEN));
        vo.setGuaranteeServiceFee(dto.getGuaranteeServiceFee());
        vo.setGuaranteeServiceFeeRate(dto.getGuaranteeServiceFee()
                .multiply(new BigDecimal(12))
                .divide(dto.getAmount(), MathContext.DECIMAL128)
                .divide(new BigDecimal(dto.getDeadline()), 4, BigDecimal.ROUND_HALF_EVEN));
        vo.setEffectiveTime(dto.getEffectiveTime());
        return Result.with(vo);
    }

    @PostMapping("/getOrgLoanContractInfo")
    @ApiOperation("获取土巴兔机构居间借款合同信息")
    public Result<OrgLoanContractResponseVO> getOrgLoanContractInfo(@RequestBody @Valid ContractRequestVO request) {
        ContractRequestDTO contractRequestDTO = new ContractRequestDTO();
        contractRequestDTO.setBorrowerUserId(request.getBorrowerUserId());
        contractRequestDTO.setProjectId(request.getProjectId());
        contractRequestDTO.setAddInvestor(request.getAddInvestor());
        contractRequestDTO.setAddAmount(request.getAddAmount());
        OrgLoanContractResponseDTO dto = investDubboService.getOrgLoanContractInfo(contractRequestDTO, String.valueOf(PrincipalContext.getUserId()));
        OrgLoanContractResponseVO vo = new OrgLoanContractResponseVO();
        vo.setContractNo(dto.getContractNo());
        for (OrgLoanContractResponseDTO.APart aPart : dto.getAPartList()) {
            OrgLoanContractResponseVO.APart aPartVO = new OrgLoanContractResponseVO.APart();
            aPartVO.setMoney(aPart.getAmount());
            aPartVO.setName(aPart.getName());
            aPartVO.setIdCard(aPart.getIdCard());
            vo.getAPartList().add(aPartVO);
        }
        vo.getBPart().setAddress(dto.getBPart().getAddress());
        vo.getBPart().setEmail("");
        vo.getBPart().setName(dto.getBPart().getName());
        vo.getBPart().setIdCard(dto.getBPart().getIdCard());
        vo.getBPart().setInstitutionalReditCode(dto.getBPart().getInstitutionalReditCode());
        vo.getBPart().setPhone(dto.getBPart().getPhone());
        vo.getCPart().setEmail("");
        vo.getCPart().setName(dto.getCPart().getName());
        vo.getBPart().setRepresentative(dto.getBPart().getRepresentative());
        vo.getCPart().setInstitutionalReditCode(dto.getCPart().getInstitutionalReditCode());
        vo.getDPart().setAddress(dto.getDPart().getAddress());
        vo.getDPart().setName(dto.getDPart().getName());
        vo.setAmount(dto.getAmount());
        vo.setDeadline(dto.getDeadline());
        vo.setDeadlineUnit(dto.getDeadlineUnit());
        vo.setBorrowRate(dto.getBorrowRate());
        vo.setBorrowRateDay(dto.getBorrowRate().divide(new BigDecimal(365), MathContext.DECIMAL128)
                .setScale(4, BigDecimal.ROUND_HALF_EVEN));
        vo.setLoanInterest(dto.getLoanInterest());
        vo.setRepaymentType(dto.getRepaymentType());
        vo.setProjectTitle(dto.getProjectTitle());
        vo.setRefundDate(dto.getRefundDate());
        vo.setPenaltyRate(dto.getPenaltyRate());
        vo.setPlatformManagementFee(dto.getPlatformManagementFee());
        vo.setPlatformManageFeeRate(dto.getPlatformManagementYearFeeRate());
        vo.setGuaranteeServiceFee(dto.getGuaranteeServiceFee());
        vo.setGuaranteeServiceFeeRate(dto.getGuaranteeServiceYearFeeRate());
        vo.setPlatformManageFeeRateDay(dto.getPlatformManagementDayFeeRate());
        vo.setGuaranteeServiceFeeRateDay(dto.getGuaranteeServiceDayFeeRate());
        vo.setEffectiveTime(dto.getEffectiveTime());
        return Result.with(vo);
    }

    @PostMapping("/getOrgPersonalFastLoanContractInfo")
    @ApiOperation("获取鸿特机构个人居间借款合同信息")
    public Result<OrgPersonalFastLoanContractResponseVO> getOrgPersonalFastLoanContractInfo(@RequestBody @Valid ContractRequestVO request) {
        ContractRequestDTO contractRequestDTO = new ContractRequestDTO();
        contractRequestDTO.setBorrowerUserId(request.getBorrowerUserId());
        contractRequestDTO.setProjectId(request.getProjectId());
        contractRequestDTO.setAddInvestor(request.getAddInvestor());
        contractRequestDTO.setAddAmount(request.getAddAmount());
        OrgPersonalFastLoanContractResponseDTO responseDTO = investDubboService.getOrgPersonalFastLoanContractResponseDTO(contractRequestDTO, String.valueOf(PrincipalContext.getUserId()));
        OrgPersonalFastLoanContractResponseVO result = new OrgPersonalFastLoanContractResponseVO();
        BeanUtils.copyProperties(responseDTO, result);
        List<OrgPersonalFastLoanContractResponseVO.APart> apartList = new ArrayList<>();
        if (Objects.nonNull(responseDTO.getAPartList()) && !responseDTO.getAPartList().isEmpty()) {
            for (OrgPersonalFastLoanContractResponseDTO.APart aPart : responseDTO.getAPartList()) {
                OrgPersonalFastLoanContractResponseVO.APart apartVo = new OrgPersonalFastLoanContractResponseVO.APart();
                BeanUtils.copyProperties(aPart, apartVo);
                apartList.add(apartVo);
            }
        }
        result.setAPartList(apartList);
        BeanUtils.copyProperties(responseDTO.getBPart(), result.getBPart());
        BeanUtils.copyProperties(responseDTO.getCPart(), result.getCPart());
        BeanUtils.copyProperties(responseDTO.getDPart(), result.getDPart());
        BeanUtils.copyProperties(responseDTO.getEPart(), result.getEPart());
        result.getBPart().setEmail("");
        result.getCPart().setEmail("");
        return Result.with(result);
    }

    @PostMapping("/getOrgCompanyFastLoanContractInfo")
    @ApiOperation("获取鸿特机构居间借款合同信息")
    public Result<OrgCompanyFastLoanContractResponseVO> getOrgCompanyFastLoanContractInfo(@RequestBody @Valid ContractRequestVO request) {
        ContractRequestDTO contractRequestDTO = new ContractRequestDTO();
        contractRequestDTO.setBorrowerUserId(request.getBorrowerUserId());
        contractRequestDTO.setProjectId(request.getProjectId());
        contractRequestDTO.setAddInvestor(request.getAddInvestor());
        contractRequestDTO.setAddAmount(request.getAddAmount());
        OrgCompanyFastLoanContractResponseDTO responseDTO = investDubboService.getOrgCompanyFastLoanContract(contractRequestDTO, String.valueOf(PrincipalContext.getUserId()));
        OrgCompanyFastLoanContractResponseVO result = new OrgCompanyFastLoanContractResponseVO();
        BeanUtils.copyProperties(responseDTO, result);
        List<OrgCompanyFastLoanContractResponseVO.APart> apartList = new ArrayList<>();
        if (Objects.nonNull(responseDTO.getAPartList()) && !responseDTO.getAPartList().isEmpty()) {
            for (OrgCompanyFastLoanContractResponseDTO.APart aPart : responseDTO.getAPartList()) {
                OrgCompanyFastLoanContractResponseVO.APart apartVo = new OrgCompanyFastLoanContractResponseVO.APart();
                BeanUtils.copyProperties(aPart, apartVo);
                apartList.add(apartVo);
            }
        }
        result.setAPartList(apartList);
        BeanUtils.copyProperties(responseDTO.getBPart(), result.getBPart());
        BeanUtils.copyProperties(responseDTO.getCPart(), result.getCPart());
        BeanUtils.copyProperties(responseDTO.getDPart(), result.getDPart());
        BeanUtils.copyProperties(responseDTO.getEPart(), result.getEPart());
        result.getBPart().setEmail("");
        result.getCPart().setEmail("");
        return Result.with(result);
    }


    @ApiOperation("投资委托授权记录")
    @PostMapping("/authorizeHistory")
    public Result<PageResponseVO<CommissionAuthorizeAgreementVO.Record>> getInvestAuthorizationHistory(@RequestBody @Valid AuthorizationHistoryQueryRequest requestVO) {
        String userId = PrincipalContext.getUserId();
        CommissionAuthHistoryRequestDTO requestDTO = new CommissionAuthHistoryRequestDTO();
        requestDTO.setUserId(userId);
        Byte authType = requestVO.getAuthType();
        switch (authType) {
            case 1:
                requestDTO.setTradeType(FadadaContractEnum.TradeTypeEnum.AUTO_INVEST);
                break;
            case 2:
                requestDTO.setTradeType(FadadaContractEnum.TradeTypeEnum.BATCH_INVEST);
                break;
            default:
                log.warn("not found tradeType for:{}", authType);
                break;
        }
        requestDTO.setPageNumber(requestVO.getPageNumber());
        requestDTO.setPageSize(requestVO.getPageSize());
        PageResponseDTO<CommissionAuthAgreementResponseDTO> responseDTO = autoInvestDubboService.queryCommissionAuthHistory(requestDTO);
        PageResponseVO<CommissionAuthorizeAgreementVO.Record> responseVO = new PageResponseVO<>();
        responseVO.setTotalCount(responseDTO.getTotalCount());
        responseVO.setTotalPage(responseDTO.getTotalPage());
        List<CommissionAuthorizeAgreementVO.Record> items = responseDTO.getItems().stream().map(dto -> {
            CommissionAuthorizeAgreementVO.Record record = new CommissionAuthorizeAgreementVO.Record();
            record.setAuthorizeId(dto.getId());
            record.setAuthorizeTime(dto.getAuthTime());
            record.setContractNo(dto.getContractNo());
            if (CommissionAuthAgreementResponseDTO.SignStatus.SIGNED == dto.getSignStatus()) {
                record.setViewUrl(dto.getViewUrl());
                record.setDownloadUrl(dto.getDownloadUrl());
            } else {
                record.setViewUrl(h5AutoInvestCommissionAuthUrl);
            }
            return record;
        }).collect(Collectors.toList());
        responseVO.setItems(items);
        return Result.with(responseVO);
    }

    @ApiOperation("投资授权预览")
    @PostMapping("/authorizePreview")
    public Result<CommissionAuthorizeAgreementVO.PreviewParam> previewInvestAuthorize() {
        String userId = PrincipalContext.getUserId();
        UserIdentityInfoResponseDTO dto = userIdentityDubboService.get(userId);
        CommissionAuthorizeAgreementVO.PreviewParam param = new CommissionAuthorizeAgreementVO.PreviewParam();
        param.setApartName(dto.getName());
        param.setApartIdCard(dto.getIdCard());
        param.setDate(new Date());
        return Result.with(param);
    }

    @ApiOperation("电子签章使用授权书预览(黄敏)")
    @PostMapping("/electronicSignaturePreview")
    public Result<EmpowermentElectronicSignatureResponseVO> electronicSignaturePreview() {
        String userId = PrincipalContext.getUserId();
        log.info("UserInvestController.empowermentElectronicSignature userId={}", userId);

        UserIdentityInfoResponseDTO dto = userIdentityDubboService.get(userId);
        EmpowermentElectronicSignatureResponseVO responseVO = new EmpowermentElectronicSignatureResponseVO();
        responseVO.setApartName(dto.getName());
        responseVO.setApartIdCard(dto.getIdCard());
        responseVO.setUserId(dto.getUserId());
        responseVO.setDateTime(new Date());

        return Result.with(responseVO);
    }

    @ApiOperation("债权转让协议预览-受让人预览(黄敏)")
    @PostMapping("/creditorTransferProtocolPreview")
    public Result<CreditorTransferProtocolPreviewResponseVO> creditorTransferProtocolPreview(@RequestBody @Valid CreditorTransferProtocolPreviewRequestVO requestVO) {
        String userId = PrincipalContext.getUserId();
        log.info("UserInvestController.creditorTransferProtocolPreview requestVO={}, userId={}", JSON.toJSONString(requestVO), userId);

        CreditorTransferProtocolPreviewResponseVO responseVO = new CreditorTransferProtocolPreviewResponseVO();
        CreditorTransferProtocolPreviewResponseDTO responseDTO = investDubboService.creditorTransferProtocolPreview(requestVO.getCreditorSaleDetailId(), requestVO.getTransferUserId(), userId);
        BeanUtils.copyProperties(responseDTO, responseVO);
        responseVO.setBorrowEmail("");
        return Result.with(responseVO);
    }

    @ApiOperation("债权转让服务风险提示书-受让人预览(黄敏)")
    @PostMapping("/creditorTransferRiskPromptPreview")
    public Result<CreditorTransferRiskPromptPreviewResponseVO> creditorTransferRiskPromptPreview(@RequestBody @Valid CreditorTransferProtocolPreviewRequestVO requestVO) {
        String userId = PrincipalContext.getUserId();
        log.info("UserInvestController.creditorTransferRiskPromptPreview requestVO={}, userId={}", JSON.toJSONString(requestVO), userId);

        CreditorTransferRiskPromptPreviewResponseVO responseVO = new CreditorTransferRiskPromptPreviewResponseVO();
        CreditorSaleDetailResponseDTO responseDTO = creditorRightsDubboService.getCreditorSaleDetail(requestVO.getCreditorSaleDetailId(), requestVO.getTransferUserId());
        UserIdentityInfoResponseDTO dto = userIdentityDubboService.get(userId);
        responseVO.setAssigneeName(dto.getName());
        responseVO.setTransferName(responseDTO.getRealName());
        responseVO.setSignDate(new Date());
        return Result.with(responseVO);
    }

    @ApiOperation("债权转让协议预览-出让人预览(黄敏)")
    @PostMapping("/saleCreditorTransferProtocolPreview")
    public Result<SaleCreditorTransferProtocolPreviewResponseVO> saleCreditorTransferProtocolPreview(@RequestBody @Valid SaleCreditorTransferProtocolPreviewRequestVO requestVO) {
        log.info("UserInvestController.saleCreditorTransferProtocolPreview requestVO={}", JSON.toJSONString(requestVO));

        SaleCreditorTransferProtocolPreviewResponseVO responseVO = new SaleCreditorTransferProtocolPreviewResponseVO();
        SaleCreditorTransferProtocolPreviewResponseDTO responseDTO = investDubboService.saleCreditorTransferProtocolPreview(requestVO.getInvestOrderId(), requestVO.getSaleAmount());
        BeanUtils.copyProperties(responseDTO, responseVO);
        responseVO.setBorrowEmail("");
        return Result.with(responseVO);
    }

    @ApiOperation("债权转让服务风险提示书-出让人预览(黄敏)")
    @PostMapping("/saleCreditorTransferRiskPromptPreview")
    public Result<SaleCreditorTransferRiskPromptPreviewResponseVO> saleCreditorTransferRiskPromptPreview() {
        String userId = PrincipalContext.getUserId();
        log.info("UserInvestController.saleCreditorTransferRiskPromptPreview userId={}", userId);

        SaleCreditorTransferRiskPromptPreviewResponseVO responseVO = new SaleCreditorTransferRiskPromptPreviewResponseVO();
        UserIdentityInfoResponseDTO dto = userIdentityDubboService.get(userId);
        responseVO.setTransferName(dto.getName());
        responseVO.setSignDate(new Date());
        return Result.with(responseVO);
    }





    /**
     * 选取合同
     *
     * @param
     *@param orgId
     * @param type  @return
     */
    private String getContractUrl(Byte borrowerType, Byte type, String orgId, Byte deadLineUnit, Byte loanType) {
        //极速借
        String url = this.h5FastloanContractUrl;
        //土巴兔
        if (ProjectTypeEnum.DECORATION_LOAN.getValue().equals(type)) {
            url = this.h5orgloanContractUrl;
            //鸿特//俊拓
        } else if (ProjectTypeEnum.ORG_SPEEDLOAN_NEW.getValue().equals(type) && ! OrgConstant.NIWOTA_ORG_ID.equals(orgId)
                && !LoanTypeEnum.BUSINESS_LOAN.getValue().equals(loanType)) {
            //企业
            if(OrgConstant.JUNTUO_ORG_ID.equals(orgId) && PeriodUnitEnum.DAY.getValue().equals(deadLineUnit)){
                if (BorrowerTypeEnum.COMPANY.getType().equals(borrowerType)) {
                    url = this.h5JunTuoCompanyFastLoanContract;  //企业
                } else {
                    url = this.h5JunTuoPersonalFastLoanContract;  //个人
                }
            } else {
                if (BorrowerTypeEnum.COMPANY.getType().equals(borrowerType)) {
                    url = this.h5OrgCompanyFastLoanContract;   //企业
                } else {
                    url = this.h5OrgPersonalFastLoanContract;  //个人
                }
            }
        }

        return url/* + CONTRACT_URL_PARAM*/;
    }

    ///////////////////V5.5.0新手投/////////////////////////////

    @ApiOperation("新手投列表(谢稳)")
    @PostMapping("/V550/noviceInvestList")
    @AuthIgnore
    public Result<NoviceInvestListResponseVO> noviceInvestList(@RequestBody NoviceInvestListRequestVO requestVO) {
        NoviceInvestListResponseVO responseVO = new NoviceInvestListResponseVO();
        NoviceInvestListRequestDTO dto = new NoviceInvestListRequestDTO();
        dto.setChannelCode(requestVO.getChannelCode());
        dto.setOffset((requestVO.getPageNumber() - 1) * requestVO.getPageSize());
        dto.setPageSize(requestVO.getPageSize());
        PageResponseDTO<InvestingProjectDTO> responseDTO = investDubboService.getNoviceInvestList(dto);
        if(!CollectionUtils.isEmpty(responseDTO.getItems())){
            for (InvestingProjectDTO investingProjectDTO : responseDTO.getItems()) {
                InvestingProjectVO vo = this.convertToInvestingProjectVO(investingProjectDTO);
                responseVO.getItems().add(vo);
            }
            responseVO.setTotalCount(responseDTO.getTotalCount());
            responseVO.setTotalPage(responseDTO.getTotalPage());
        }
        return Result.with(responseVO);
    }

    @ApiOperation("新手BANNER图片和相关信息(谢稳)")
    @PostMapping("/V550/noviceInvestInfos")
    @AuthIgnore
    public Result<NoviceInvestInfoResponseVO> noviceInvestInfos(@RequestBody NoviceInvestInfoRequestVO requestVO) {
        String userId = PrincipalContext.getUserId();
        if (userId != null) {
            boolean limit = accessRateLimiter.userLimit(userId, "noviceInvest_infos", 1, AccessRateLimiter.Unit.SECOND, 10);
            if (limit) {
                throw new BizException("SYS1001");  //亲爱的用户，您操作频率过快，请稍后再试
            }
        }
        NoviceInvestInfoResponseVO responseVO = new NoviceInvestInfoResponseVO();
        requestVO.setChannelCode(null);
        NoviceInvestInfoResponseDTO responseDTO = investDubboService.getNoviceInvestInfos(userId,requestVO.getChannelCode());
        responseVO.setIsNovice(responseDTO.getIsNovice());
        responseVO.setNoviceInvestBannerUrl(responseDTO.getNoviceInvestBannerUrl());
        responseVO.setNoviceSurplusDays(responseDTO.getNoviceSurplusDays());
        responseVO.setNoviceSurplusInvestMoney(responseDTO.getNoviceSurplusInvestMoney());
        responseVO.setRoleDefinitionDays(responseDTO.getRoleDefinitionDays());
        if (StringUtils.isBlank(userId)) {
            responseVO.setNoviceHint("赶快登录查看您可享受的加息额度吧~");
            return Result.with(responseVO);
        }
        if (responseDTO.getIsNovice() == null) {
            return Result.with(responseVO);
        }
        if (responseDTO.getIsNovice() == (byte) 0) {
            responseVO.setNoviceHint("您的新手专享标福利已过期，去看看其他标的吧~");
        }
        if (responseDTO.getIsNovice() == (byte) 1) {
            responseVO.setNoviceHint(responseDTO.getNoviceSurplusInvestMoney().compareTo(BigDecimal.ZERO) == 0 ?
                    "您的新手专享标额度已用完，去看看其他标的吧~" :
                    ("您的新手加息额度还剩" + responseDTO.getNoviceSurplusInvestMoney().intValue() + "元"));
        }
        return Result.with(responseVO);
    }

    ////////////////////////////////////////////////////////////

}

